/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package gpsmap;

/**
 * this class is modified form of travel sailsman's source code
 * @author Mahdi Abdinejadi, Navid Ranjbar, Amirhossein Tayarani
 */
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import org.jdesktop.swingx.JXMapViewer;
import org.jdesktop.swingx.mapviewer.DefaultWaypointRenderer;
import org.jdesktop.swingx.mapviewer.GeoPosition;
import org.jdesktop.swingx.mapviewer.Waypoint;
import org.jdesktop.swingx.mapviewer.WaypointRenderer;
import org.jdesktop.swingx.painter.AbstractPainter;
import org.openstreetmap.osmosis.core.domain.v0_6.*;

/**
 * Paints waypoints on the JXMapViewer. This is an instance of
 * Painter that only can draw on to JXMapViewers.
 * @author Mahdi Abdinejadi, Navid Ranjbar, Amirhossein Tayarani
 */
public class WaypointPainter<T extends JXMapViewer> extends AbstractPainter<T> {
	private WaypointRenderer renderer = new DefaultWaypointRenderer();
	private static Set<Waypoint> waypoints;
	private static ArrayList<Node> node = new ArrayList<Node>();
	private static Waypoint startWP = new Waypoint();
        private static Waypoint targetWP = new Waypoint();
	public void setNodes(ArrayList<Node> node){
		this.node = node;
	}
	public void setStartTargetWaypoint(Waypoint startWP, Waypoint targetWP){
	    this.startWP = startWP;
	    this.targetWP = targetWP;
	           System.out.println("set start target way points");
	}
        public void setStarttWaypoint( double lat, double lon){
         this.startWP = new Waypoint(lat, lon);
        }

	/**
	 * Creates a new instance of WaypointPainter
	 */
	public WaypointPainter() {
		setAntialiasing(true);
		setCacheable(false);
		waypoints = new HashSet<Waypoint>();
	}

	/**
	 * Sets the waypoint renderer to use when painting waypoints
	 * @param r the new WaypointRenderer to use
	 */
	public void setRenderer(WaypointRenderer r) {
		this.renderer = r;
	}

	/**
	 * Gets the current set of waypoints to paint
	 * @return a typed Set of Waypoints
	 */
	public Set<Waypoint> getWaypoints() {
		return waypoints;
	}

	/**
	 * Sets the current set of waypoints to paint
	 * @param waypoints the new Set of Waypoints to use
	 */
	public void setWaypoints(Set<Waypoint> waypoints) {
		this.waypoints = waypoints;
	}

	/**
	 * {@inheritDoc}
	 * @param g
	 * @param map
	 * @param width
	 * @param height
         * @author Mahdi Abdinejadi
	 */
	@Override
	protected void doPaint(Graphics2D g, T map, int width, int height) {
		if (renderer == null) {
			return;
		}

		//figure out which waypoints are within this map viewport
		//so, get the bounds
		Rectangle viewportBounds = map.getViewportBounds();
		int zoom = map.getZoom();
		Dimension sizeInTiles = map.getTileFactory().getMapSize(zoom);
		int tileSize = map.getTileFactory().getTileSize(zoom);
		Dimension sizeInPixels = new Dimension(sizeInTiles.width*tileSize, sizeInTiles.height*tileSize);

		double vpx = viewportBounds.getX();
		// normalize the left edge of the viewport to be positive
		while(vpx < 0) {
			vpx += sizeInPixels.getWidth();
		}
		// normalize the left edge of the viewport to no wrap around the world
		while(vpx > sizeInPixels.getWidth()) {
			vpx -= sizeInPixels.getWidth();
		}

		// create two new viewports next to eachother
		Rectangle2D vp2 = new Rectangle2D.Double(vpx,
				viewportBounds.getY(),viewportBounds.getWidth(),viewportBounds.getHeight());
		Rectangle2D vp3 = new Rectangle2D.Double(vpx-sizeInPixels.getWidth(),
				viewportBounds.getY(),viewportBounds.getWidth(),viewportBounds.getHeight());
		g.setColor(Color.BLACK);
		for (Waypoint w : getWaypoints()) {
			Point2D point = map.getTileFactory().geoToPixel(w.getPosition(), map.getZoom());
			if (vp2.contains(point)) {

				int x = (int)(point.getX() - vp2.getX());
				int y = (int)(point.getY() - vp2.getY());
				int xs = (int)(map.getTileFactory().geoToPixel(startWP.getPosition(), map.getZoom()).getX() - vp2.getX());
				int ys = (int)(map.getTileFactory().geoToPixel(startWP.getPosition(), map.getZoom()).getY() - vp2.getY());
				int xt = (int)(map.getTileFactory().geoToPixel(targetWP.getPosition(), map.getZoom()).getX() - vp2.getX());
				int yt = (int)(map.getTileFactory().geoToPixel(targetWP.getPosition(), map.getZoom()).getY() - vp2.getY());				
				g.fillOval(x, y, 7, 7);
				//g.translate(x,y);
				
				//g.translate(-x,-y);
				g.translate(xs,ys);
				paintWaypoint(startWP, map, g);
				g.translate(-xs,-ys);
				g.translate(xt,yt);
				paintWaypoint(targetWP, map, g);
				g.translate(-xt,-yt);

			}
			if (vp3.contains(point)) {
				 int x = (int)(point.getX() - vp3.getX());
				 int y = (int)(point.getY() - vp3.getY());
				 int xs = (int)(map.getTileFactory().geoToPixel(startWP.getPosition(), map.getZoom()).getX() - vp3.getX());
				 int ys = (int)(map.getTileFactory().geoToPixel(startWP.getPosition(), map.getZoom()).getY() - vp3.getY());
				 int xt = (int)(map.getTileFactory().geoToPixel(targetWP.getPosition(), map.getZoom()).getX() - vp3.getX());
				 int yt = (int)(map.getTileFactory().geoToPixel(targetWP.getPosition(), map.getZoom()).getY() - vp3.getY());
				g.translate(x,y);
				g.fillRect(x, y, 10, 10);
				g.translate(-x,-y);
				g.translate(xs,ys);
				paintWaypoint(startWP, map, g);
				g.translate(-xs,-ys);
				g.translate(xt,yt);
				paintWaypoint(targetWP, map, g);
				g.translate(-xt,-yt);
			}
		}

		g.setColor(Color.red);


		//        RouteDrawer routeDrawer = new RouteDrawer();
		//        MemoryDataSet MDSmap = (new org.openstreetmap.osm.io.FileLoader(new File("//D:/project/my attemp/lind_map.osm"))).parseOsm();
		//
		for (int i=0 ; !node.isEmpty() ; i++){
			if (i >= node.size()-1)
				break;
//                        else{

			g.drawLine(
					(int) (map.getTileFactory().geoToPixel(new GeoPosition(node.get(i).getLatitude(),node.get(i).getLongitude()),map.getZoom()).getX()- vp2.getX()),
					(int) (map.getTileFactory().geoToPixel(new GeoPosition(node.get(i).getLatitude(),node.get(i).getLongitude()),map.getZoom()).getY()- vp2.getY()),
					(int) (map.getTileFactory().geoToPixel(new GeoPosition(node.get(i+1).getLatitude(),node.get(i+1).getLongitude()),map.getZoom()).getX()- vp2.getX()),
					(int) (map.getTileFactory().geoToPixel(new GeoPosition(node.get(i+1).getLatitude(),node.get(i+1).getLongitude()),map.getZoom()).getY()- vp2.getY()));
		}
                if(!node.isEmpty()){
		g.drawLine(
			(int) (map.getTileFactory().geoToPixel(new GeoPosition(node.get(node.size()-1).getLatitude(),node.get(node.size()-1).getLongitude()),map.getZoom()).getX()- vp2.getX()),
			 (int) (map.getTileFactory().geoToPixel(new GeoPosition(node.get(node.size()-1).getLatitude(),node.get(node.size()-1).getLongitude()),map.getZoom()).getY()- vp2.getY()),	
			  (int)(map.getTileFactory().geoToPixel(targetWP.getPosition(), map.getZoom()).getX() - vp2.getX()),
			   (int)(map.getTileFactory().geoToPixel(targetWP.getPosition(), map.getZoom()).getY() - vp2.getY())
		);
                g.setColor(Color.BLUE);
                g.drawOval((int)(map.getTileFactory().geoToPixel(targetWP.getPosition(), map.getZoom()).getX() - vp2.getX()),
			   (int)(map.getTileFactory().geoToPixel(targetWP.getPosition(), map.getZoom()).getY() - vp2.getY()),
                           10, 10);
               }
                g.setColor(Color.yellow);
                g.fillOval((int)(map.getTileFactory().geoToPixel(targetWP.getPosition(), map.getZoom()).getX() - vp2.getX())+1,
			   (int)(map.getTileFactory().geoToPixel(targetWP.getPosition(), map.getZoom()).getY() - vp2.getY())+1,
                           9, 9);
//        }
        g.setColor(Color.ORANGE);
		        g.fillRect(
                                (int) (map.getTileFactory().geoToPixel(startWP.getPosition(), map.getZoom()).getX()- vp2.getX()),
                                (int) (map.getTileFactory().geoToPixel(startWP.getPosition(), map.getZoom()).getY()- vp2.getY())
                                , 10, 10);

		//        g.setColor(Color.blue);
		//        g.drawOval(10, 10, 10, 10);
		//        g.setColor(Color.BLACK);
		//        g.fillOval(12, 12, 6, 6);
		//System.out.println(zoom );
	}
	/**
	 * <p>Override this method if you want more control over how a
	 * waypoint is painted than what you can get by just
	 * plugging in a custom waypoint renderer. Most developers should not
	 * need to override this method and can use a WaypointRenderer
	 * instead.</p>
	 *
	 *
	 * <p>This
	 * method will be called to each waypoint with the
	 * graphics object pre-translated
	 * so that 0,0 is at the center of the waypoint.
	 * This saves the developer from having
	 * to deal with lat/long => screen coordinate transformations.</p>
	 * @param w the current waypoint
	 * @param map the current map
	 * @param g the current graphics context
	 * @see setRenderer(WaypointRenderer)
	 * @see WaypointRenderer
	 */
	protected void paintWaypoint(final Waypoint w, final T map, final Graphics2D g) {
		renderer.paintWaypoint(g, map, w);
	}

	private static void p(String str) {
		System.out.println(str);
	}

}